package com.tianji.learning.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.cache.CategoryCache;
import com.tianji.api.client.course.CatalogueClient;
import com.tianji.api.client.course.CategoryClient;
import com.tianji.api.client.course.CourseClient;
import com.tianji.api.client.search.SearchClient;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.course.CataSimpleInfoDTO;
import com.tianji.api.dto.course.CourseSimpleInfoDTO;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.autoconfigure.mq.RabbitMqHelper;
import com.tianji.common.constants.MqConstants;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BadRequestException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.QuestionFormDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.QuestionAdminPageQuery;
import com.tianji.learning.domain.query.QuestionPageQuery;
import com.tianji.learning.domain.vo.QuestionAdminVO;
import com.tianji.learning.domain.vo.QuestionVO;
import com.tianji.learning.enums.QuestionStatus;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.mq.message.PointsMessage;
import com.tianji.learning.service.IInteractionQuestionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.learning.service.IInteractionReplyService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.querydsl.QPageRequest;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动提问的问题表 服务实现类
 * </p>
 *
 * @author fx
 * @since 2024-08-25
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class InteractionQuestionServiceImpl
        extends ServiceImpl<InteractionQuestionMapper, InteractionQuestion>
        implements IInteractionQuestionService {

    private final InteractionReplyMapper replyMapper;
    private final UserClient userClient;
    private final SearchClient searchClient;//根据课程名称查询课程id集合
    private final CourseClient courseClient;
    private final CatalogueClient catalogueClient;
    private final CategoryCache categoryCache;
    private final RabbitMqHelper mqHelper;

    /**
     * 01 客户端--新增 互动问题（day05-随堂-01）
     *
     * @param formDTO
     */
    @Override
    public void addQuestion(QuestionFormDTO formDTO) {
        // 1 数据格式转换 dto -> po
        InteractionQuestion question = BeanUtils.copyBean(formDTO, InteractionQuestion.class);

        // 2 添加缺失的数据 -- userId
        question.setUserId(UserContext.getUser());

        // 3 向数据库中添加数据
        this.save(question);

    }

    /**
     * 02 客户端--分页查询 互动问题-客户端（day05-随堂-02）
     *
     * @param pageQuery
     * @return
     */
    @Override
    public PageDTO<QuestionVO> pageQueryQuestions(QuestionPageQuery pageQuery) {
        // 1 校验数据 课程id与小节id不能同时为空
        if (ObjectUtils.isEmpty(pageQuery.getCourseId()) && ObjectUtils.isEmpty(pageQuery.getSectionId())) {
            throw new BadRequestException("课程id与小节id不能同时为空");
        }

        // 2 分页查询问题数据
        // select * from interaction_question where  course_id =? and section_id =? and hidden = false
        // order by id desc limit ?,?
        // 由于不需要问题的具体描述，减少返回数据，需要过滤去除description字段
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .select(InteractionQuestion.class, column -> !column.getColumn().equals("description")) //过滤去除description字段
                .eq(ObjectUtils.isNotEmpty(pageQuery.getCourseId()), InteractionQuestion::getCourseId, pageQuery.getCourseId())
                .eq(ObjectUtils.isNotEmpty(pageQuery.getSectionId()), InteractionQuestion::getSectionId, pageQuery.getSectionId())
                .eq(pageQuery.getOnlyMine(), InteractionQuestion::getUserId, UserContext.getUser())
                .eq(InteractionQuestion::getHidden, false)
                .page(pageQuery.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = pageResult.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        // 3 查询 缺失数据
        // 3.1 获取 1、提问者userId列表 2、最近一次回答的id列表 3、最近一次回答的userId
        // 注意判断 是否隐藏用户信息
        Set<Long> userIds = new HashSet<>();
        Set<Long> latestAnswerIds = new HashSet<>(records.size());
        for (InteractionQuestion record : records) {
            if (!record.getAnonymity()) {
                userIds.add(record.getUserId());
            }
            latestAnswerIds.add(record.getLatestAnswerId());
        }

        // 3.2 根据最近一次回答的id列表查询 最新回答信息
        Map<Long, InteractionReply> latestReplyInfoMap = new HashMap<>();
        List<InteractionReply> latestReplyInfo = replyMapper.selectBatchIds(latestAnswerIds);
        if (ObjectUtils.isNotEmpty(latestReplyInfo)) {
            for (InteractionReply reply : latestReplyInfo) {
                latestReplyInfoMap.put(reply.getId(), reply);

                if (!reply.getAnonymity()) {
                    userIds.add(reply.getUserId()); //3、最近一次回答的userId添加到userId列表中
                }
            }
        }

        // 3.3 根据userId列表查询 用户信息
        Map<Long, UserDTO> userInfoMap = new HashMap<>();
        List<UserDTO> userDTOs = userClient.queryUserByIds(userIds);
        if (ObjectUtils.isNotEmpty(userDTOs)) {
            userInfoMap = userDTOs.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        }

        // 4 填充缺失信息到vo中 ，并添加到voList中
        List<QuestionVO> voList = new ArrayList<>();
        for (InteractionQuestion record : records) {
            // 4.1 po -> vo
            QuestionVO questionVO = BeanUtils.copyBean(record, QuestionVO.class);

            // 4.2 填充提问者信息-不隐藏（ 昵称，头像）
            UserDTO userInfo = userInfoMap.get(record.getUserId());
            if (ObjectUtils.isNotEmpty(userInfo)) {
                if (!record.getAnonymity()) {
                    questionVO.setUserName(userInfo.getName());
                    questionVO.setUserIcon(userInfo.getIcon());
                }
            }
            // 4.3 填充最新一次回答信息-不隐藏 （昵称），内容
            InteractionReply latestReply = latestReplyInfoMap.get(record.getLatestAnswerId());
            if (ObjectUtils.isNotEmpty(latestReply)) {
                questionVO.setLatestReplyContent(latestReply.getContent());
                if (!latestReply.getAnonymity()) {
                    UserDTO userDTO = userInfoMap.get(latestReply.getUserId());
                    if (ObjectUtils.isNotEmpty(userDTO)) {
                        questionVO.setLatestReplyUser(userDTO.getName());
                    }
                }
            }

            // 4.3 添加vo到voList中
            voList.add(questionVO);
        }

        // 5 返回PageDTO
        return PageDTO.of(pageResult, voList);
    }

    /**
     * 03 客户端--根据id查询 互动问题详情（day05-随堂-03）
     *
     * @param id 问题id
     * @return
     */
    @Override
    public QuestionVO queryQuestionById(Long id) {
        // 未看清楚要求的错误示例
        /*// 1 根据问题id查询问题信息
        InteractionQuestion record = this.lambdaQuery()
                .eq(InteractionQuestion::getId, id)
                .eq(InteractionQuestion::getHidden, false)
                .one();
        if (ObjectUtils.isEmpty(record)) {
            return null;
        }
        // 2 查询缺失的相关信息
        // 2.0 准备用户信息id集合
        Set<Long> userIds = new HashSet<>();
        // 2.1 查询最近一次回答信息 ，填充vo最新一次回答内容， 获取用户id
        InteractionReply reply = replyService.getById(record.getLatestAnswerId());
        if (ObjectUtils.isNotEmpty(reply)) {
            if (!reply.getAnonymity()) {
                userIds.add(reply.getUserId());
            }
        }
        // 2.2 查询提出问题的用户信息（昵称，头像），最近一次回答的回答者信息，并转换为map
        if (!record.getAnonymity()) {
            userIds.add(record.getUserId());
        }
        List<UserDTO> userDTOs = userClient.queryUserByIds(userIds);
        Map<Long, UserDTO> userInfoMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(userDTOs)) {
            userInfoMap = userDTOs.stream().collect(Collectors.toMap(UserDTO::getId, Function.identity()));
        }

        // 3 po -> vo 填充缺失信息
        QuestionVO vo = BeanUtils.copyBean(record, QuestionVO.class);
        // 3.1 填充vo提问者信息
        UserDTO userInfo = userInfoMap.get(record.getUserId());
        if (ObjectUtils.isNotEmpty(userInfo)) {
            if (!record.getAnonymity()) {
                vo.setUserName(userInfo.getName());
                vo.setUserIcon(userInfo.getIcon());
            }
        }
        // 3.2 填充最新一次回答信息
        if (ObjectUtils.isNotEmpty(reply)) {
            vo.setLatestReplyContent(reply.getContent());
            if (!reply.getAnonymity()) {
                UserDTO userDTO = userInfoMap.get(reply.getUserId());
                if (ObjectUtils.isNotEmpty(userDTO)) {
                    vo.setLatestReplyUser(userDTO.getName());
                }
            }
        }

        // 4 返回vo
        return vo;*/
        // 1 根据问题id查询课程信息
        InteractionQuestion question = this.getById(id);
        if (ObjectUtils.isEmpty(question) || question.getHidden()) {
            return null;
        }

        // 2 查询提问者信息 注意判断是否隐藏用户信息
        UserDTO userDTO = null;
        if (!question.getAnonymity()) {
            userDTO = userClient.queryUserById(question.getUserId());
        }

        // 3 po -> vo 填充缺失信息 并返回
        QuestionVO vo = BeanUtils.copyBean(question, QuestionVO.class);
        if (ObjectUtils.isNotEmpty(userDTO)) {
            vo.setUserName(userDTO.getName());
            vo.setUserIcon(userDTO.getIcon());
        }
        return vo;
    }

    /**
     * 04 管理端--分页查询 互动问题（day05-随堂-04）
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<QuestionAdminVO> adminPageQueryQuestions(QuestionAdminPageQuery query) {
        // 0  如果传入了课程名称 根据课程名称，查询课程id集合
        List<Long> courseIds = null;
        if (ObjectUtils.isNotEmpty(query.getCourseName())) {
            courseIds = searchClient.queryCoursesIdByName(query.getCourseName());
            if (ObjectUtils.isEmpty(courseIds)) {
                return PageDTO.empty(0l, 0l);
            }
        }
        // 1 根据分页条件，分页查询问题
        Page<InteractionQuestion> pageResult = this.lambdaQuery()
                .in(ObjectUtils.isNotEmpty(courseIds), InteractionQuestion::getCourseId, courseIds)
                .eq(ObjectUtils.isNotEmpty(query.getStatus()), InteractionQuestion::getStatus, query.getStatus())
                .ge(ObjectUtils.isNotEmpty(query.getBeginTime()), InteractionQuestion::getCreateTime, query.getBeginTime())
                .le(ObjectUtils.isNotEmpty(query.getEndTime()), InteractionQuestion::getCreateTime, query.getEndTime())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        List<InteractionQuestion> records = pageResult.getRecords();
        if (ObjectUtils.isEmpty(records)) {
            return PageDTO.empty(pageResult);
        }

        // 2 查询缺失信息，并进行必要的封装，方便后续填充字段
        // 2.0 准备courseId集合 章节id集合、用户id集合
        Set<Long> cIds = new HashSet<>();           //课程id集合
        Set<Long> catalogueIds = new HashSet<>();   //章节id集合
        Set<Long> userIds = new HashSet<>();        //用户id集合
        Set<Long> catagory = new HashSet<>();       //课程分类id集合
        for (InteractionQuestion record : records) {
            cIds.add(record.getCourseId());
            //注意章节id包括 章、节
            catalogueIds.add(record.getChapterId());
            catalogueIds.add(record.getSectionId());

            userIds.add(record.getUserId());

        }

        // 2.1 查询 课程信息 转换map，方便后续查询
        List<CourseSimpleInfoDTO> courseInfoList = courseClient.getSimpleInfoList(cIds);
        Map<Long, CourseSimpleInfoDTO> courseInfoMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(courseInfoList)) {
            courseInfoMap = courseInfoList.stream().collect(Collectors.toMap(CourseSimpleInfoDTO::getId, Function.identity()));
        }

        // 2.2 查询 章节信息 转换map，方便后续查询
        List<CataSimpleInfoDTO> cataInfoList = catalogueClient.batchQueryCatalogue(catalogueIds);
        Map<Long, String> cataInfoMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(cataInfoList)) {
            cataInfoMap = cataInfoList.stream().collect(Collectors.toMap(CataSimpleInfoDTO::getId, CataSimpleInfoDTO::getName));
        }

        // 2.3 查询提问者信息 转换map，方便后续查询
        List<UserDTO> userInfoList = userClient.queryUserByIds(userIds);
        Map<Long, String> userInfoMap = new HashMap<>();
        if (ObjectUtils.isNotEmpty(userInfoList)) {
            userInfoMap = userInfoList.stream().collect(Collectors.toMap(UserDTO::getId, UserDTO::getName));
        }

        List<QuestionAdminVO> voList = new ArrayList<>();
        // 3 遍历records，转换成vo 添加到voList，并填充缺失的信息
        for (InteractionQuestion record : records) {
            // 3.1 po -> vo
            QuestionAdminVO adminVO = BeanUtils.copyBean(record, QuestionAdminVO.class);

            // 3.1 填充提问者昵称
            adminVO.setUserName(userInfoMap.getOrDefault(record.getUserId(),""));

            // 3.2 填充章、节名称
            adminVO.setChapterName(cataInfoMap.getOrDefault(record.getChapterId(), ""));
            adminVO.setSectionName(cataInfoMap.getOrDefault(record.getSectionId(), ""));

            // 3.3 填充课程名称、课程分类名称拼接
            CourseSimpleInfoDTO courseInfo = courseInfoMap.get(record.getCourseId());
            if (ObjectUtils.isNotEmpty(courseInfo))
            {
                adminVO.setCourseName(courseInfo.getName());
                // 填充课程分类信息
               adminVO.setCategoryName(categoryCache.getCategoryNames(courseInfo.getCategoryIds()));
            }

            // 添加adminVo到voList
            voList.add(adminVO);
        }

        // 4 返回pageDTO
        return PageDTO.of(pageResult, voList);
    }

    /**
     * 05 删除互动问题（day05-练习）
     *
     * @param id
     */
    @Override
    public void deleteQuestionById(Long id) {

    }
}



















